#ifndef __RING_QUEUE_H__
#define __RING_QUEUE_H__
#include <mutex>


class ScopeMutex
{
public:
	ScopeMutex(std::mutex& m):mutex(m)
	{
		m.lock();
	}

	~ScopeMutex()
	{
		mutex.unlock();
	}

	std::mutex& mutex;
};

template <typename T, int MAX>
class RingQueue
{
public:
	RingQueue();
	virtual ~RingQueue();

	bool Push(const T& item);
	bool Pop(T& item);

	bool IsEmpty()const;
	bool IsFull()const;

private:
	uint32_t _IncIndex(uint32_t index)const;

private:
	volatile uint32_t m_nTail;
	volatile uint32_t m_nHead;
	T m_stItems[MAX + 1];
	std::mutex m_mutex;
};

template <typename T, int MAX>
RingQueue<T, MAX>::RingQueue():m_nTail(0),m_nHead(0)
{
}

template <typename T, int MAX>
RingQueue<T, MAX>::~RingQueue()
{
}

template <typename T, int MAX>
bool RingQueue<T, MAX>::Push(const T& item)
{
	ScopeMutex sm(m_mutex);
	uint32_t nextTail = _IncIndex(m_nTail);
	if (nextTail != m_nHead)
	{
		m_stItems[m_nTail] = item;
		m_nTail = nextTail;
		return true;
	}

	return false;
}

#if 0
template <typename T, int MAX>
T* RingQueue<T, MAX>::GetFree()
{
	ScopeMutex sm(m_mutex);
	uint32_t nextTail = _IncIndex(m_nTail);
	if (nextTail == m_nHead)
	{
		return NULL;
	}

	// ������ʽĬ�Ϲ���
	T* pT = &(m_stItems[m_nTail]); //new (&(m_stItems[m_nTail])) T;
	return pT;
}

template <typename T, int MAX>
bool RingQueue<T, MAX>::PushFree()
{
	ScopeMutex sm(m_mutex);
	uint32_t nextTail = _IncIndex(m_nTail);
	if (nextTail != m_nHead)
	{
		//m_stItems[m_nTail] = item;
		m_nTail = nextTail;
		return true;
	}

	return false;
}
#endif

template <typename T, int MAX>
bool RingQueue<T, MAX>::Pop(T& item)
{
	ScopeMutex sm(m_mutex);
	if (m_nHead == m_nTail)
	{
		return false;
	}

	item = m_stItems[m_nHead];
	m_nHead = _IncIndex(m_nHead);

	return true;
}

#if 0
template <typename T, int MAX>
T* RingQueue<T, MAX>::Get()
{
	ScopeMutex sm(m_mutex);
	if (m_nHead == m_nTail)
	{
		return NULL;
	}

	return &(m_stItems[m_nHead]);
}

template <typename T, int MAX>
bool RingQueue<T, MAX>::Pop()
{
	ScopeMutex sm(m_mutex);
	if (m_nHead == m_nTail)
	{
		return false;
	}

	m_nHead = _IncIndex(m_nHead);
	return true;
}
#endif

template <typename T, int MAX>
bool RingQueue<T, MAX>::IsEmpty()const
{
	ScopeMutex sm(m_mutex);
	return m_nHead == m_nTail;
}

template <typename T, int MAX>
bool RingQueue<T, MAX>::IsFull()const
{
	ScopeMutex sm(m_mutex);
	uint32_t nextTail = _IncIndex(m_nTail);
	return (nextTail == m_nHead);
}

template <typename T, int MAX>
uint32_t RingQueue<T, MAX>::_IncIndex(uint32_t index)const
{
	return (index + 1) % (MAX + 1);
}
#endif
